/**
 * 获取当前URL地址的请求参数
 */
export function parseQuery(url) {
    let query = url.split('?')[1] || '';
    let result = {};
    query.split('&').forEach(item => {
        let [key, value] = item.split('=');
        result[key] = value;
    });
    return result;
}
// console.log(parseQuery('http://localhost:3016/setting/permission/personnel?a=1&b=2')); 测试 { a: '1', b: '2' }

/**
 * 使用正则表达式获取当前URL地址的请求参数
 */
export function parseQuery2(url) {
    const URL = url
    return JSON.parse(`{"${decodeURI(URL.split('?')[1]).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"')}"}`)
}
// console.log(parseQuery2('http://localhost:3016/setting/permission/personnel?a=1&b=2')); 测试 { a: '1', b: '2' }

/**
 * 获取一个随机颜色
 * @returns 返回一个随机颜色，HEX值
 */
export function getRandomColor() {
    return `#${Math.floor(Math.random() * 0xffffff).toString(16)}`;
}

// console.log(getRandomColor());

/**
 * 特殊字符处理的长度
 * @param {string} str 字符串
 * @returns 字符串的长度
 */
export function pointLength(str) {
    let len = 0
    if (!str) return 0
    for (let i = 0; i < str.length;) {
        const codePoint = str.charCodeAt(i)
        i += codePoint > 0xffff ? 2 : 1
        len++
    }
    return len
}

/**
 * 格式化数据，数据为空时显示 '-'
 * @param {any} value 数据
 * @param {string} type 数据类型
 */
export function formatData(value, type) {
    const rules = ["", null, undefined, "null"];

    if (rules.some((r) => r === value)) {
        return "-";
    }
    return value + type;
}

/**
 *  检查某个值是否是空的
 * @param {*} n 要检查的值
 * @returns [] | '' | {} | undefined | null 这些值均返回true
 */
export const isEmpty = (n) => {
    if (n === undefined || n === null) {
        return true;
    } else if (isString(n)) {
        return n.trim() === "";
    } else if (isArray(n)) {
        return !n.length;
    } else if (isObject(n)) {
        return !Object.keys(n).length;
    }
    return false;
};

/**
 * 手机号码本地脱敏
 * @param {string} phone 手机号码
 * @returns 脱敏后的手机号码
 */
export const desPhone = (phone) => {
    typeof phone !== "string" && (phone = "");
    return phone.replace(/^(.{3})(.*)(.{4})$/, "$1****$3");
};

/**
 * 身份证本地脱敏
 * @param {string} card 身份证号码
 * @returns 脱敏后的身份证号码
 */
export const desIdcard = (card) => {
    typeof card !== "string" && (card = "");
    return card.replace(
        /^(.{2})(.*)(.{2})$/,
        (match, p1, p2, p3) => {
            return `${p1}${p2.replace(/[\w\W]/g, "*")}${p3}`;
        },
    );
};

/**
 * 文件名截取
 * @param {string} uri 文件路径
 * @returns 文件后缀名
 */
export const getFileName = (uri) => {
    if (!uri) return "";
    const pathNames = new URL(uri).pathname.split("/");
    const name = pathNames[pathNames.length - 1 ?? 0];
    return name;
};

/**
 * 下载文件
 * @param {string} url 文件地址
 * @param {string} name 文件名称
 */
export const downloadFile = (url, name) => {
    const a = document.createElement("a");
    a.href = url;
    a.download = name;
    a.click();
    a.remove();
}

/**
 * 保存文件
 */
export const saveFile = (blob, fileName) => {
    const a = document.createElement("a");
    a.href = URL.createObjectURL(blob);
    a.download = fileName ?? '未命名文件';
    a.click();
    a.remove();
}

function isImageType(fileType) {
    return ["png", "jpg", "jpeg"].includes(fileType);
}

/**
 * 下载图片
 * @param {string} url 图片地址
 * @param {string} name 文件名称
 */
export const downloadImg = (url, name) => {
    const fileType = getFileName(url).split(".").pop();
    if (!isImageType(fileType)) {
        return;
    }
    const img = new Image();
    img.src = url;
    img.onload = () => {
        const canvas = document.createElement("canvas");
        const ctx = canvas.getContext("2d");
        canvas.width = img.width;
        canvas.height = img.height;
        ctx.drawImage(img, 0, 0, img.width, img.height);
        const dataUrl = canvas.toDataURL("image/png");
        downloadFile(dataUrl, name);
    };
}

/**
 * 获取指定日期前n天
 * @param {Date} date
 * @param {number} n
 * @returns {string} YYYY-MM-DD格式的日期字符串
 */
export const getBeforeDate = (date, n) => {
    let d = new Date(date);
    d.setDate(d.getDate() - n);
    let m = d.getMonth() + 1;
    return d.getFullYear() + '-' + m + '-' + d.getDate();
}
// console.log(getBeforeDate('2002-10-02', 2));

/**
 * 获取当前日期，并格式化为 'YYYY-MM-DD hh:mm:ss'， 不足十位的补充零
 * @returns {string} YYYY-MM-DD hh:mm:ss格式的日期字符串
 */
export const getNowDate = () => {
    let date = new Date();
    let year = date.getFullYear();
    let month = date.getMonth() + 1;
    let day = date.getDate();
    let hour = date.getHours();
    let minute = date.getMinutes();
    let second = date.getSeconds();
    if (month < 10) month = '0' + month;
    if (day < 10) day = '0' + day;
    if (hour < 10) hour = '0' + hour;
    if (minute < 10) minute = '0' + minute;
    if (second < 10) second = '0' + second;
    return year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second;
}
// console.log(getNowDate());

/**
 * 判断是否为字符串
 * @param {string} str 字符串
 * @returns 是否为字符串
 */
export function isString(str) {
    return Object.prototype.toString.call(str) === "[object String]";
}

/**
 * 判断是否为数组
 * @param {Array} arr 数组
 * @returns 是否为数组
 */
export function isArray(arr) {
    return Array.isArray(arr);
}

/**
 * 判断是否为对象
 * @param {Object} obj 对象
 * @returns 是否为对象
 */
export function isObject(obj) {
    return Object.prototype.toString.call(obj) === "[object object]";
}

/**
 * 判断参数是否是一个方法
 * @param {Function} func 方法
 * @returns 是否为方法
 */
export function isFunction(func) {
    return Object.prototype.toString.call(func) === "[object Function]";
}

/**
 * 判断是否是数字
 * @param {Number|String} n  要判断的数
 * @param {Boolean} strict 默认为true,即严格模式:只能是Number类型， false则判断String类型是否也满足是数字的情况
 */
export const isNumber = (n, strict = true) => {
    const isStrictNumber =
        Object.prototype.toString.call(n) === "[object Number]" &&
        !Number.isNaN(n) &&
        Number.isFinite(n);
    if (strict) {
        return isStrictNumber;
    }
    return isStrictNumber || (isString(n) && /^-?\d+(\.\d+)?$/.test(n));
};
// console.log(isNumber('22', false));

/**
 * 判断是否是一个整数
 * @param {number} num 数字
 * @param {boolean} strict 是否严格模式，默认为true，只能是Number类型， false则判断String类型是否也满足是数字的情况
 */
export function isInteger(num, strict = true) {
    if (!isNumber(num, strict)) return false;
    return num % 1 === 0;
}

/**
 * 过滤权限路由
 * @param {Array} routes 路由
 * @param {Array} permissions 权限数组
 * @returns 有权限的路由
 */
export const getPermissionRoutes = (routes, permissions) => {
    const filterRoutes = (routes) => {
        let tempRoutes = []
        for (const route of routes) {
            if (permissions.includes(route.key)) {
                const tempRoute = {
                    ...route,
                    children: route.children?.length ? filterRoutes(route.children) : []
                }
                tempRoutes.push(tempRoute)
            }
        }
        return tempRoutes
    }

    const permissionRoutes = filterRoutes(routes)

    return permissionRoutes
}

// console.log(getPermissionRoutes(
//     [
//         {
//             name: 'aaa',
//             key: 'menu_aaa',
//             children: [
//                 {
//                     name: 'aaa-1',
//                     key: 'menu_aaa_1',
//                 }
//             ]
//         },
//         {
//             name: 'bbb',
//             key: 'menu_bbb',
//             children: []
//         }
//     ],
//     ['menu_aaa', 'menu_aaa_1']
// ));

/**
 * 数组扁平化
 * 结构简单的数组，如： [1, 2, [3, 4]]
 */
export const flattenSimpleArray = (arr) => {
    return arr.reduce((prev, curr) => {
        return prev.concat(Array.isArray(curr) ? flattenSimpleArray(curr) : curr)
    }, [])
}
// console.log([1, 2, [3, 4]]);
// console.log(flattenSimpleArray([1, 2, [3, 4]]))

// 测试路由数据
const routes = [
    {
        name: 'aaa',
        key: 'menu_aaa',
        children: [
            {
                name: 'aaa-1',
                key: 'menu_aaa_1',
                children: [
                    {
                        name: 'aaa-1-1',
                        key: 'menu_aaa_1_1',
                    }
                ]
            },
            {
                name: 'aaa-2',
                key: 'menu_aaa_2',
            }
        ]
    },
    {
        name: 'bbb',
        key: 'menu_bbb',
        children: [
            {
                name: 'bbb-1',
                key: 'menu_bbb_1',
                children: [
                    {
                        name: 'bbb-1-1',
                        key: 'menu_bbb_1_1',
                    }
                ]
            }
        ]
    }
]

/**
 * 路由扁平化工具
 * @param {Array} arr 路由数组
 * @returns 扁平化后的数组
 */
export const flattenRoutes = (routes) => {
    const flattenComplexArray = (arr) => {
        return arr.reduce((prev, curr) => {
            prev.push({
                name: curr.name,
                key: curr.key,
            })
            curr.children?.length && prev.push(...flattenComplexArray(curr.children))
            return prev
        }, [])
    }
    return flattenComplexArray(routes)
}
// console.log(flattenRoutes(routes));

/**
 * 格式化数组，转换为 {key: value} 形式，如：[{value: 1, label: 'a'}]
 * @param {Array} arr 需要格式化的数组
 * @param {Array} formatData 参与格式化数据的键名
 * @param {string} keyNameArray 格式化后的键名
 * @description 用于类似下拉框，多选框，单选框的选项
 */
export const formatArray = (
    arr,
    formatData = [],
    keyNameArray = ['value', 'label']
) => {

    if (!isArray(arr)) {
        throw new Error('arr must be an array')
    }
    if (!isArray(formatData)) {
        throw new Error('formatData must be an array') 
    }
    if (!isArray(keyNameArray)) {
        throw new Error('keyNameArray must be an array')
    }
    return arr.reduce((prev, curr) => {
        prev.push({
            [keyNameArray[0]]: curr[formatData[0]],
            [keyNameArray[1]]: curr[formatData[1]]
        })
        return prev
    }, [])
}
// console.log(formatArray([
//     {
//         id: '1002',
//         name: '张三',
//         age: 18,
//         sex: '男',
//         phone: '13888888888'
//     }, {
//         id: '1003',
//         name: '李四',
//         age: 19,
//         sex: '男',
//         phone: '13999999999'
//     }
// ], ['phone', 'name']));

/**
 * 
 */